//函数中的类型 1：函数的声明方式  2：函数的参数 3：函数的返回值

//function关键字来声明的函数可以提升到当前作用域顶部

//对于ts来说 function关键和const add1=function有区别， function关键字声明的函数 不能标注函数类型

//通过表达式来申明的函数：必须赋予的值要满足定义的类型（要求有一个兼容性在里面）
function add(x, y) {
    return x + y;
}

//1）函数的定义(x: any, y: any) => any |  { (x: any, y: any): any }

// type Add = (x: any, y: any) => any;
// type Add ={ (x: any, y: any): any };
// const sum: Add = function (x:string,y:string) {
//     return x + y;
// }
//如果表明函数类型，再使用的时候以表明的函数为准

//2） 参数  可选参数 ?是可选参数和 string | undefined 必须得传参,可选参数只能在列表参数的后面
//=是默认值  y:string='1'  y?:string

//例如：y?:string  y:string | undefined
//const sum = function和const sum: Add = function (x:string,y:string)的区别是一样的，sum = function可推导出类型，
//type Add ={ (x: string, y: string): string };
const sum = function (x:string,y:string='1') {
    return x + y;
}
//这里如果是兼容处理，采用的是默认值的方式，不是你赋值的类型  type Add ={ (x: string, y?: string): string };
sum('1')


//3、参数this问题
// 尽量不采用this 来作为函数的上下文，this的缺陷就是类型推导问题

//如果想限制this的类型，那么需要手动指定this类型
function getValue(this:IPerson,key:Ikeys) {    //this不是形参，是标明参数的类型
    // return this[key];
    return 1
}
//我想根据值来 获取类型 typeof  配合type来声明新的类型
const person = {name: 'jack', age: 18,address:'邯郸大名'}

type IPerson = typeof person;//提取对象的类型为IPerson type类型会提升到顶部

type Ikeys = keyof IPerson;//提取对象的key为Ikey
//可以将子类型赋予给父类型  子类型：IPerson  父类型：{name:string,age:number}
getValue.call(person, 'name');

//函数中有arguments 但是我们不建议使用
function sum2(...args:number[]) { // 函数编程:入参和返回值 ，组合式api和函数编程不是一个东西哦！但是他们都是函数编程（不考虑使用this和arguments）
   return args.reduce((prev, current) => prev + current, 0);

}

//参数的类型直接参数后面:标识 ，函数的返回值在 { }前面来标识
//            表达式的类型 ↓               参数的类型↓ 
//const sum3: (...args:any[]) => any = (...args:any[]):any => { 函数主要是考虑兼容性，什么样的函数赋给什么样的函数 这可能是我们所关心的

const sum3: (...args:any[]) => any = (...args:any[]):any => {
    return args.reduce((prev, current) => prev + current, 0);
}

//ts 中函数有一个概念：重载(类型的重载)，对于强类语言可以一个函数写多遍(参数不同)，js实现重载靠的是arguments

//入参是一个字符串 或者是数字 => ['字符串']  ['数字']
//string[]|number[]代表是数组里存的都是字符串和数组里存的都是number  (number|string)[]代表数组里面可以放number和string

//根据不同的入参(value:string|number)来有不同的返回时(string[]|number[]),我们需要考虑来通过类型的重载来实现

function toArray2(value:string):string[];//函数的重载
function toArray2(value:number):number[];//函数的重载
//上面的声明，仅仅是类型上的重载
function toArray2(value:string|number):string[]|number[] { //函数的实现
    return []
}    
let arr = toArray2('1')//string[]
let arr2 = toArray2(1)//number[]



export { }//解决ts文件报错问题  模块化的问题
